home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / video / fly8111-.000 / fly8111- / fly8 / objects.c < prev    next >
C/C++ Source or Header  |  1979-12-31  |  10KB  |  449 lines

  1. /* --------------------------------- objects.c ------------------------------ */
  2.  
  3. /* This is part of the flight simulator 'fly8'.
  4.  * Author: Eyal Lebedinsky (eyal@ise.canberra.edu.au).
  5. */
  6.  
  7. /* Some generic object behaviour routines and hit detection.
  8. */
  9.  
  10. #include "plane.h"
  11.  
  12.  
  13. /* how many object refreshes are allowed each frame
  14. */
  15. static int    RefreshPerFrame = 1;
  16.  
  17. /* hit routines.
  18. */
  19. extern void FAR
  20. object_rand (OBJECT *obj, int speed, int extent, int noise)
  21. {
  22.     int    e, i;
  23.  
  24.     if (O_GTARGET != obj->name) {
  25.         e =  SH(obj)->extent;
  26.         if (!e)
  27.             e = 1;
  28.         if (extent/64 <= e) {
  29.             if (0 == (i = SH(obj)->extent))
  30.                 i = 1;
  31.             i = muldiv (speed/64, extent, i);
  32.         } else
  33.             i = speed;
  34.         if (i) {
  35.             obj->V[X] += Frand () % i;
  36.             obj->V[Y] += Frand () % i;
  37.             obj->V[Z] += Frand () % i;
  38.         }
  39.         i = 0x7fff/e;
  40.         if (i) {
  41.             obj->speed = ihypot3d (obj->V);
  42.             obj->da[X] = Frand ()%i-i/2;
  43.             obj->da[Y] = Frand ()%i-i/2;
  44.             obj->da[Z] = Frand ()%i-i/2;
  45.         }
  46.     }
  47.  
  48.     if (noise && st.quiet)
  49.         Snd->Effect (EFF_HIT, SND_ON);
  50. }
  51.  
  52. extern int FAR
  53. object_break (int n, int speed, int extent, int noise)
  54. {
  55.     int    i;
  56.     OBJECT    *p;
  57.  
  58.     for (i = 0; i < n; ++i) {
  59.         if (!(p = create_object (O_BROKEN, 1)))
  60.             break;
  61.         p->flags |= F_HIT;
  62.         object_rand (p, speed, extent, noise);
  63.     }
  64.     return (i);
  65. }
  66.  
  67. extern void FAR
  68. object_hit (OBJECT *obj, int seed, int speed, int extent, int damaging)
  69. {
  70.     Fsrand (seed);
  71.  
  72.     obj->damage -= damaging;
  73.  
  74.     if (obj == CC) {
  75.         MsgWPrintf (50, "damage %d", obj->damage);
  76.         if (st.quiet)
  77.             Snd->Effect (EFF_DAMAGE, SND_ON);
  78.     }
  79.  
  80.     st.bodies[obj->name]->hit (obj, speed, extent, damaging);
  81.  
  82.     if (obj->flags & F_EXPORTED)    /* exported victim */
  83.         remote_imhit (obj, seed, speed, extent, damaging);
  84. }
  85.  
  86. LOCAL_FUNC int NEAR
  87. hit (VECT p, VECT d, int r)    /* initial distance p, closure speed r */
  88. {
  89.     long    x, y, z, s, t;
  90.  
  91.     x = p[X];
  92.     y = p[Y];
  93.     z = p[Z];
  94.  
  95.     s = x*d[X]+y*d[Y]+z*d[Z];
  96.     if (s < 0)        /* objects getting away from each other */
  97.         return (0);
  98.     if (s > 0) {
  99.         t = d[X]*(long)d[X]+d[Y]*(long)d[Y]+d[Z]*(long)d[Z];
  100.         if (s >= t) {
  101. #if 0
  102.             x -= d[X];    /* not really needed now */
  103.             y -= d[Y];
  104.             z -= d[Z];
  105. #endif
  106.             return (0);    /* objects will be closer */
  107.         } else {
  108.             x -= d[X]*s/t;
  109.             y -= d[Y]*s/t;
  110.             z -= d[Z]*s/t;
  111.         }
  112.     }
  113.  
  114. #if 0
  115.     return ((x*x+y*y+z*z) < r*(long)r);
  116. #else
  117.     return (est_hyp ((int)x, (int)y, (int)z) < (Uint)r);
  118. #endif
  119. }
  120.  
  121. LOCAL_FUNC void NEAR
  122. check_hit (OBJECT *p, int interval)
  123. {
  124.     register int    hit_dist;
  125.     register OBJECT    *w;
  126.     int        t2, extent;
  127.     long        t1, t3;
  128.     VECT        r, d, V;
  129.     LVECT        R;
  130.     OBJECT        *owner;
  131.  
  132.     if (!(p->shflags & SH_HIT) &&
  133.         (st.flags & SF_BLANKER || !(p->flags & F_HIT)))
  134.         return;
  135.  
  136.     if (p->flags & F_IMPORTED)        /* ignore foreign bullets */
  137.         return;
  138.  
  139.     V[X] =  p->V[X]/VONE;
  140.     V[Y] =  p->V[Y]/VONE;
  141.     V[Z] =  p->V[Z]/VONE;
  142.  
  143.     R[X] =  p->R[X]/VONE;
  144.     R[Y] =  p->R[Y]/VONE;
  145.     R[Z] =  p->R[Z]/VONE;
  146.  
  147.     extent = SH(p)->extent;
  148.     owner = p->owner;
  149.  
  150.     for (w = COT; w; w = w->prev) {
  151.         if (!(w->shflags & SH_BEHIT))
  152.             break;            /* all BEHIT's are at end! */
  153.         if (w == p || (w == owner && w->id == p->ownerid))
  154.             continue;
  155.         if (w->flags & F_DEL)
  156.             continue;
  157.         if (w->tom > st.present)    /* immature? */
  158.             continue;
  159.  
  160.         hit_dist = fmul (FONE/4*3, SH(w)->extent + extent);
  161.  
  162.         t1 = w->R[X]/VONE - R[X];
  163.         t2 = TADJ(w->V[X]/VONE - V[X]);
  164.         t3 = t1 - t2;
  165.         if (t1 >  hit_dist && t3 >  hit_dist)
  166.             continue;
  167.         if (t1 < -hit_dist && t3 < -hit_dist)
  168.             continue;
  169.         r[X] = (int)t1;
  170.         d[X] = t2;
  171.  
  172.         t1 = w->R[Y]/VONE - R[Y];
  173.         t2 = TADJ(w->V[Y]/VONE - V[Y]);
  174.         t3 = t1 - t2;
  175.         if (t1 >  hit_dist && t3 >  hit_dist)
  176.             continue; 
  177.         if (t1 < -hit_dist && t3 < -hit_dist)
  178.             continue;
  179.         r[Y] = (int)t1;
  180.         d[Y] = t2;
  181.  
  182.         t1 = w->R[Z]/VONE - R[Z];
  183.         t2 = TADJ(w->V[Z]/VONE - V[Z]);
  184.         t3 = t1 - t2;
  185.         if (t1 >  hit_dist && t3 >  hit_dist)
  186.             continue;
  187.         if (t1 < -hit_dist && t3 < -hit_dist)
  188.             continue;
  189.         r[Z] = (int)t1;
  190.         d[Z] = t2;
  191.  
  192.         if (hit (r, d, hit_dist)) {
  193.             if (!(w->flags & F_HIT) &&
  194.                  owner && owner->id == p->ownerid)
  195.                     ++p->owner->score;
  196.             p->flags |= F_HIT|F_MOD;
  197.             p->color = ST_FIRE1;
  198.             if (w->flags & F_IMPORTED)    /* imported victim */
  199.                 remote_urhit (w, p->speed, extent,
  200.                     p->damaging);
  201.             else                /* local victim */
  202.                 object_hit (w, rand(), p->speed, extent,
  203.                     p->damaging);
  204.         }
  205.     }
  206. }
  207.  
  208. /* objects handling.
  209. */
  210.  
  211. #define NM    (1852*VONE)
  212.  
  213. extern void FAR
  214. object_update (OBJECT *p, int interval)
  215. {
  216.     int    tx, ty;
  217.  
  218.     p->R[X] += (tx = TADJ (p->V[X]));
  219.     p->R[Y] += (ty = TADJ (p->V[Y]));
  220.     p->R[Z] += TADJ (p->V[Z]);
  221.  
  222.     if (p->flags & F_KEEPNAV) {
  223.         p->longmin += tx;
  224.         tx = fmul (NM, COS(muldiv(p->latitude, D90, 90*60)));
  225.         if (tx) {
  226.             while (p->longmin >= tx) {
  227.                 p->longmin -= tx;
  228.                 if (++p->longitude >= 180*60)
  229.                     p->longitude -= 360*60;
  230.             }
  231.             while (p->longmin < 0) {
  232.                 p->longmin += tx;
  233.                 if (--p->longitude < -180*60)
  234.                     p->longitude += 360*60;
  235.             }
  236.         }
  237.  
  238.         p->latmin += ty;
  239.         for (;;) {
  240.             if (p->latmin >= NM) {
  241.                 p->latmin -= NM;
  242.                 if (++p->latitude >= 90*60) {
  243.                     p->latitude = 180*60 - p->latitude;
  244.                     p->latmin = -p->latmin;
  245.                 }
  246.             } else if (p->latmin < 0) {
  247.                 p->latmin += NM;
  248.                 if (--p->latitude <= -90*60) {
  249.                     p->latitude = -180*60 - p->latitude;
  250.                     p->latmin = -p->latmin;
  251.                 }
  252.             } else
  253.                 break;
  254.         }
  255.     }
  256.  
  257.     if (p->time != FOREVER) {
  258.         p->time -= muldiv (interval, TIMEPSEC, 1000);
  259.         if (p->time <= 0)
  260.             p->flags |= F_DEL;    /* no notification */
  261.     }
  262. }
  263.  
  264. #undef NM
  265.  
  266. extern void FAR
  267. object_dynamics (OBJECT *p, int interval)
  268. {
  269.     BODY    *b;
  270.     int    save_interval;
  271.  
  272.     if (p->flags & F_DONE)
  273.         return;
  274.     p->flags |= F_DONE;
  275.  
  276.     st.owner = p;
  277.     b = st.bodies[p->name];
  278.  
  279.     if (p->flags & F_IMPORTED) {
  280.         remote_receive (p);
  281.         Frandomize ();        /* the net syncs the machines */
  282.         if (ET_IMPORTED == p->e_type && EIM(p)->timeout < st.present) {
  283.             p->flags |= F_DEL;        /* object timeout */
  284.             ++STATS_NETERRLOST;
  285.         } else {
  286.             save_interval = st.interval;
  287.             st.interval = (int)(st.present - p->rtime);
  288.             if (st.interval) {
  289.                 if (st.interval > 1000)    /* ignore long pauses */
  290.                     st.interval = 1000;
  291.                 else if (st.interval < -1000)
  292.                     st.interval = -1000;
  293.                 if (b->shape->flags & SH_LOCALSIM)
  294.                     b->dynamics (p, st.interval);
  295.                 else
  296.                     gen_dynamics (p, st.interval);
  297.                 p->rtime = st.present;
  298.             }
  299.             st.interval = save_interval;
  300.         }
  301.     } else {
  302.         b->dynamics (p, interval);
  303.         check_hit (p, interval);
  304.     }
  305. }
  306.  
  307. extern int FAR
  308. objects_dynamics (int interval)
  309. {
  310.     OBJECT    *p, *q;
  311.     int    refreshed;
  312.  
  313.     remote_receive (0);
  314.     Frandomize ();        /* the net syncs the machines */
  315.  
  316.     Tm->Interval (TMR_START, 0L);
  317.     for (p = CO; p; p = p->next) {
  318.         if (T(q = p->owner) && p->ownerid == q->id)
  319.             object_dynamics (q, interval);
  320.         object_dynamics (p, interval);
  321.     }
  322.     STATS_TIMESIM += Tm->Interval (TMR_STOP, 10000L);
  323.  
  324.     remote_refresh ();
  325.     players_flush ();    /* del bad messages */
  326.     players_purge ();    /* del bad players */
  327.  
  328. /* If I am deleted then create a new local player. Copy some of the old
  329.  * plane settings to the new.
  330. */
  331.     if (CC->flags & F_DEL) {
  332.         int    font;
  333.  
  334.         p = CC;
  335.         st.options = st.ptype;
  336.         font = font_set (-1);
  337.         if (!(CC = create_object (O_PLANE, 1))) {
  338.             MsgEPrintf (-50, "no new plane");
  339.             return (1);
  340.         }
  341.         font_set (font);
  342.         MsgPrintf (50, "new plane");
  343.         if (T(CC->pointer = p->pointer))
  344.             (*CC->pointer->control->Center)(CC->pointer);
  345.  
  346.         CC->pointer->l[9] = 100;    /* brake */
  347.  
  348.         EE(CC)->flags |= EE(p)->flags;
  349.         EE(CC)->hud  = EE(p)->hud;
  350.         EE(CC)->hud1 = EE(p)->hud1;
  351.         EE(CC)->hud2 = EE(p)->hud2;
  352.         EE(CC)->hud3 = EE(p)->hud3;
  353.         EE(CC)->hudmode = EE(p)->hudmode;
  354.         EE(CC)->hdd = EE(p)->hdd;
  355.         EE(CC)->ladder = EE(p)->ladder;
  356.         EE(CC)->radar = EE(p)->radar;
  357.         EE(CC)->hudarea = EE(p)->hudarea;
  358.         EE(CC)->tapelen = EE(p)->tapelen;
  359.         EE(CC)->weapon = EE(p)->weapon;
  360.         EE(CC)->ils = EE(p)->ils;
  361.         EE(CC)->hudshift = EE(p)->hudshift;
  362.         EE(CC)->ldgap = EE(p)->ldgap;
  363.         EE(CC)->ldstep = EE(p)->ldstep;
  364.         EE(CC)->ldstep0 = EE(p)->ldstep0;
  365.         EE(CC)->ldstepg = EE(p)->ldstepg;
  366.         EE(CC)->ldtip = EE(p)->ldtip;
  367.         EE(CC)->ldndash = EE(p)->ldndash;
  368.         EE(CC)->hudFontSize = EE(p)->hudFontSize ;
  369.         CC->flags |= p->flags & ~(F_HIT|F_DEL);
  370.         CC->gpflags = p->gpflags;
  371.         if (!(CC->gpflags & GPF_PILOT))
  372.             CC->flags |= F_STEALTH;        /* wait for pilot */
  373.         CC->color = ST_FRIEND;
  374.         CC->score  = p->score;
  375.         p->pointer = 0;
  376.         CC->viewport = p->viewport;
  377.         p->viewport = 0;
  378.         if (st.flags & SF_BLANKER)
  379.             EE(CC)->weapon = WE_M61;
  380.         for (q = CO; q; q = q->next) {
  381.             if (O_BROKEN == q->name && q->owner == p) {
  382.                 q->owner = CC;
  383.                 q->ownerid = CC->id;
  384.             }
  385.         }
  386.         place_plane (CC, st.home);
  387.     }
  388.  
  389.     if (CV->flags & F_DEL) {
  390.         if (T(p = CV->owner) && p->id == CV->ownerid &&
  391.             !(p->flags & F_DEL)) {
  392.             CV = p;
  393.         } else
  394.             CV = CC;
  395.         if (CV->viewport)
  396.             get_viewport (CV);
  397.     }
  398.  
  399. /* export, refresh and delete as needed.
  400. */
  401.     refreshed = 0;
  402.     st.ntargets = 0;
  403.     for (p = CO; p;) {
  404.         if (p->flags & F_EXPORTED) {
  405.             if (refreshed < RefreshPerFrame &&
  406.                 !(p->flags & (F_DEL|F_NEW|F_ALIVE))) {
  407.                 p->flags |= F_MOD|F_ALIVE;
  408.                 ++refreshed;
  409.             }
  410.             send_obj (p, st.all_pports);
  411.         }
  412.  
  413.         if (p->flags & F_DEL) {
  414.             p = delete_object (p);
  415.             continue;
  416.         }
  417.  
  418.         if ((p->name == O_TARGET || p->name == O_GTARGET)
  419.             && !(p->flags & F_HIT))
  420.             ++st.ntargets;
  421.         p->flags &= ~(F_NEW|F_MOD|F_DONE);
  422.         p = p->next;
  423.     }
  424.  
  425. /* If a refresh cycle has ended, check to see if a new one should be
  426.  * scheduled. If the cycle is too short or too long then adjust it.
  427. */
  428.     if (0 == refreshed) {
  429.         if (st.present < st.RefreshTime - TO_REFRESH/4) {
  430.             if (--RefreshPerFrame <= 0)
  431.                 ++RefreshPerFrame;
  432.             else            /* force a cycle */
  433.                 st.RefreshTime = st.present;
  434.         }
  435.         if (st.present >= st.RefreshTime) {
  436.             for (p = CO; p; p = p->next)
  437.                 if (p->flags & F_EXPORTED)
  438.                     p->flags &= ~F_ALIVE;
  439.             st.RefreshTime = st.present + TO_REFRESH;
  440.         }
  441.     } else if (st.present > st.RefreshTime + TO_REFRESH/4) {
  442.         ++RefreshPerFrame;    /* missed one, so hurry up */
  443.         st.RefreshTime = st.present + TO_REFRESH/4;
  444.     }
  445.  
  446.     send_obj (0, 0);            /* flush netports */
  447.     return (0);
  448. }
  449.